#ifndef __EPOLL_SERVER_HPP__
#define __EPOLL_SERVER_HPP__

#include <iostream>
#include <string>
#include <functional> // 引入std::function
#include <cassert>    // 断言库
#include "Log.hpp"    // 日志模块头文件
#include "Sock.hpp"   // 套接字操作模块头文件
#include "Epoll.hpp"  // Epoll操作模块头文件

namespace ns_epoll
{ // 命名空间定义，避免命名冲突

    // 常量定义
    const static int default_port = 8080; // 默认监听端口
    const static int gnum = 64;           // epoll事件数组默认大小

    // EpollServer类，基于epoll实现的服务器框架
    class EpollServer
    {
    public:
        // 使用函数对象作为请求处理回调类型
        using func_t = std::function<void(std::string)>;

    private:
        // 私有成员变量
        int _listensock;           // 监听socket描述符
        int _epfd;                 // epoll文件描述符
        uint16_t _port;            // 监听端口
        int _revs_num;             // epoll事件数组大小
        struct epoll_event *_revs; // 存储epoll事件的数组
        func_t _HandlerRequest;    // 请求处理函数

    public:
        // 构造函数，初始化服务器并设置监听
        EpollServer(func_t HandlerRequest, const int &port = default_port)
            : _port(port), _revs_num(gnum), _HandlerRequest(HandlerRequest)
        {
            // 分配epoll事件数组空间
            _revs = new struct epoll_event[_revs_num];

            // 创建监听socket
            _listensock = Sock::Socket();
            Sock::Bind(_listensock, _port);
            Sock::Listen(_listensock);

            // 创建epoll实例
            _epfd = Epoll::CreateEpoll();
            logMessage(DEBUG, "init success, listensock: %d, epfd: %d", _listensock, _epfd);

            // 将listensock，先添加到epoll中，让epoll帮我们管理起来
            if (!Epoll::CtlEpoll(_epfd, EPOLL_CTL_ADD, _listensock, EPOLLIN))
                exit(6);
            logMessage(DEBUG, "add listensock to epoll success.");
        }

        // 启动服务器主循环
        void Start()
        {
            int timeout = -1; // 无超时等待
            while (true)
            {
                LoopOnce(timeout);
            }
        }

        // 单次事件循环处理
        void LoopOnce(int timeout)
        {
            int n = Epoll::WaitEpoll(_epfd, _revs, _revs_num, timeout); // 等待epoll事件，n为发生的事件数量
            switch (n)
            {
            case 0: // 如果没有事件发生（超时）
                logMessage(DEBUG, "No events, timeout.");
                break;
            case -1:                                                        // 发生错误
                logMessage(ERROR, "Epoll wait error: %s", strerror(errno)); // 记录错误信息
                break;
            default: // 成功等待到事件
                logMessage(DEBUG, "get a event");
                HandlerEvents(n); // 调用事件处理器处理所有就绪事件
                break;
            }
        }

        // 事件处理器，处理epoll返回的所有事件
        void HandlerEvents(int n)
        {
            assert(n > 0);              // 断言确保至少有一个事件需要处理
            for (int i = 0; i < n; ++i) // 遍历所有就绪事件
            {
                uint32_t revents = _revs[i].events; // 当前事件类型
                int sock = _revs[i].data.fd;        // 事件关联的文件描述符

                if (revents & EPOLLIN) // 检查是否为读事件就绪
                {
                    if (sock == _listensock)   // 1. 如果是监听套接字事件，表示有新连接
                        Accepter(_listensock); // 调用Accepter接受新连接
                    else                       // 2. 否则，普通套接字有数据可读
                        Recver(sock);          // 调用Recver处理接收到的数据
                }

                // TODO: 可以在此处添加其他事件类型的处理逻辑，如EPOLLOUT处理写事件
            }
        }

        // 接受新连接
        void Accepter(int listensock)
        {
            std::string clientip;
            uint16_t clientport;
            int sock = Sock::Accept(listensock, &clientip, &clientport); // 接受连接，获取客户端信息
            if (sock < 0)
            {
                logMessage(WARNING, "accept error!"); // 接受失败，记录警告
                return;
            }

            // 将新连接的套接字添加到epoll中，监听读事件
            if (!Epoll::CtlEpoll(_epfd, EPOLL_CTL_ADD, sock, EPOLLIN))
                return; // 添加失败则直接返回，此处应有更详细的错误处理

            logMessage(DEBUG, "add new sock : %d to epoll success", sock); // 添加成功，记录日志
        }

        // 处理接收到的数据
        void Recver(int sock)
        {
            char buffer[10240];
            ssize_t n = recv(sock, buffer, sizeof(buffer) - 1, 0); // 从sock接收数据

            if (n > 0) // 数据接收成功
            {
                buffer[n] = 0;           // 确保字符串结尾
                _HandlerRequest(buffer); // 调用用户定义的回调函数处理数据
            }
            else if (n == 0) // 客户端关闭连接
            {
                // 移除epoll对该sock的关注，并关闭连接
                bool res = Epoll::CtlEpoll(_epfd, EPOLL_CTL_DEL, sock, 0);
                assert(res); // 确保移除成功
                (void)res;
                close(sock);
                logMessage(NORMAL, "client %d quit, me too...", sock);
            }
            else // 发生错误
            {
                // 同样移除epoll监控并关闭连接
                bool res = Epoll::CtlEpoll(_epfd, EPOLL_CTL_DEL, sock, 0);
                assert(res);
                (void)res;
                close(sock);
                logMessage(NORMAL, "client recv %d error, close error sock", sock);
            }
        }

        // 析构函数，清理资源
        ~EpollServer()
        {
            if (_listensock >= 0)
                close(_listensock);
            if (_epfd >= 0)
                close(_epfd);
            if (_revs)
                delete[] _revs;
        }
    };

} // namespace ns_epoll

#endif // __EPOLL_SERVER_HPP__